﻿Ext.data.ServerProxy = Ext.extend(Ext.data.Proxy, {

    //赋给一个请求的'page'参数的名称。默认为'page'。如果你不想发送一个代表页面的参数，设置为undefined，
    pageParam: 'page',

    //赋给一个请求的'start'参数的名称。默认为'start'。如果你不想发送一个代表开始的参数，设置为undefined，
    startParam: 'start',

    //赋给一个请求的'limit'参数的名称。默认为'limit'。如果你不想发送一个代表记录数的参数，设置为undefined，
    limitParam: 'limit',

    //赋给一个请求的'group'参数的名称。默认为'group'。如果你不想发送一个代表分组的参数，设置为undefined，
    groupParam: 'group',

    //赋给一个请求的'sort'参数的名称。默认为'sort'。如果你不想发送一个代表分组的参数，设置为undefined，
    sortParam: 'sort',

    //赋给一个请求的'filter'参数的名称。默认为'filter'。如果你不想发送一个代表筛选的参数，设置为undefined，
    filterParam: 'filter',

    //默认为true。向请求加入一个独特的参数名称以禁用高速缓存。
    noCache: true,

    //缓存参数的名称,当使用noCache时用于添加到URL中。（默认为“_dc”）
    cacheString: "_dc",

    //请求响应的等待时间。 默认为30秒.
    timeout: 30000,


    constructor: function (config) {
        config = config || {};

        Ext.data.ServerProxy.superclass.constructor.call(this, config);

        //每次请求中包含的额外的参数。当请求的个别参数与额外参数冲突，将覆盖额外参数
        this.extraParams = config.extraParams || {};


        this.nocache = this.noCache;
    },


    create: function () {
        return this.doRequest.apply(this, arguments);
    },

    //执行读操作
    read: function () {
        return this.doRequest.apply(this, arguments);
    },

    update: function () {
        return this.doRequest.apply(this, arguments);
    },

    destroy: function () {
        return this.doRequest.apply(this, arguments);
    },

    //创建并返回一个Ext.data.Request对象，该对象基于Store传给当前Proxy的参数。
    buildRequest: function (operation) {

        //每次请求中包含的额外的参数。当请求的个别参数与额外参数冲突，将覆盖额外参数
        var params = Ext.applyIf(operation.params || {}, this.extraParams || {});

        //重新组织参数结构
        params = Ext.applyIf(params, this.getParams(params, operation));

        //创建一个请求对象
        var request = new Ext.data.Request({
            params: params,            //HTTP请求的参数。可以被代理对象和回写对象访问并修改。 
            action: operation.action,  //当前请求表示的动作名称。通常为'create', 'read', 'update' 或 'destroy'的其中之一。
            records: operation.records,//
            operation: operation       //当前操作
        });

        //请求访问的url
        request.url = this.buildUrl(request);


        operation.request = request;//将请求赋予操作

        return request;
    },


    encodeSorters: function (sorters) {
        var min = [],
            length = sorters.length,
            i;

        for (i = 0; i < length; i++) {
            min[i] = {
                property: sorters[i].property,
                direction: sorters[i].direction
            };
        }

        return Ext.encode(min);
    },


    encodeFilters: function (filters) {
        var min = [],
            length = filters.length,
            i;

        for (i = 0; i < length; i++) {
            min[i] = {
                property: filters[i].property,
                value: filters[i].value
            };
        }

        return Ext.encode(min);
    },


    encodeGroupers: function (group) {
        return Ext.encode(group);
    },

    //重新组织参数结构，返回组织后的参数
    getParams: function (params, operation) {
        params = params || {};

        var group = operation.group,       //可选的分组配置参数。仅适用于“读”操作。
            sorters = operation.sorters,   //可选的排序对象数组。仅适用于“读”操作。
            filters = operation.filters,   //可选的筛选对象数组。仅适用于“读”操作。
            page = operation.page,
            start = operation.start,       //起始索引（偏移），在页面运行的一个“读”操作时使用。
            limit = operation.limit,       //要加载的记录数。用于分页时的“读”操作。

            pageParam = this.pageParam,    //赋给一个请求的'page'参数的名称。默认为'page'。
            startParam = this.startParam,  //赋给一个请求的'start'参数的名称。默认为'start'。
            limitParam = this.limitParam,  //赋给一个请求的'limit'参数的名称。默认为'limit'。
            groupParam = this.groupParam,  //赋给一个请求的'group'参数的名称。默认为'group'。
            sortParam = this.sortParam,    //赋给一个请求的'sort'参数的名称。默认为'sort'。
            filterParam = this.filterParam;//赋给一个请求的'filter'参数的名称。默认为'filter'。

        if (pageParam && page) {
            params[pageParam] = page;
        }

        if (startParam && start) {
            params[startParam] = start;
        }

        if (limitParam && limit) {
            params[limitParam] = limit;
        }

        if (groupParam && group && group.field) {
            params[groupParam] = this.encodeGroupers(group);//将字符串转化为其他形式
        }

        if (sortParam && sorters && sorters.length > 0) {
            params[sortParam] = this.encodeSorters(sorters);
        }

        if (filterParam && filters && filters.length > 0) {
            params[filterParam] = this.encodeFilters(filters);
        }

        return params;
    },

    //生成一个URL，该URL基于给定的Ext.data.Request对象。
    //默认情况下，ServerProxy的buildUrl方法会把cache-buster参数追加加到URL的末尾。
    //ServerProxy的子类可能需要对URL进行额外的修改。
    buildUrl: function (request) {
        var url = request.url || this.url;

        if (!url) {
            throw new Error("You are using a ServerProxy but have not supplied it with a url.");
        }

        //this.noCache默认为true。向请求加入一个独特的参数名称以禁用高速缓存。
        if (this.noCache) {
            //向一个URL查询字符串追加内容,把请求时间追加到URL中
            url = Ext.urlAppend(url, Ext.util.Format.format("{0}={1}", this.cacheString, (new Date().getTime())));
        }

        return url;
    },


    doRequest: function (operation, callback, scope) {
        throw new Error("The doRequest function has not been implemented on your Ext.data.ServerProxy subclass. See src/data/ServerProxy.js for details");
    },


    afterRequest: Ext.emptyFn,

    onDestroy: function () {
        Ext.destroy(this.reader, this.writer);

        Ext.data.ServerProxy.superclass.destroy.apply(this, arguments);
    }
});